package com.fingard.dsp.bank.directbank.hebbank01;

import com.fingard.constant.Format;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptData;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptDataHelper;
import com.fingard.dsp.bank.dbobj.updownfile.DownFileHelper;
import com.fingard.dsp.bank.dbobj.updownfile.DownFileRecord;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directConfig.ReceiptProConfig;
import com.fingard.dsp.bank.directConfig.TaskTimerSet;
import com.fingard.dsp.bank.directbank.bankInterface.IScheduleTask;
import com.fingard.dsp.bank.sepro.ReceiptPro;
import com.fingard.dsp.task.DelayCounter;
import com.fingard.dsp.task.command.SyncReceipt;
import com.fingard.generalobj.ExecResponse;
import com.fingard.io.FileHelper;
import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.util.ZipHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import com.fingard.FGBiz;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Parker on 2020-03-10.
 * @version 1.0
 */
public class HEBBANK01ScheduleTask extends HEBBANK01Base implements IScheduleTask {
    private String logCode = "ZJRC01" + File.separator + "TaskReceiptPro";
    private TaskTimerSet timer;
    private ReceiptProConfig proConfig;
    private static DelayCounter delayCounter = new DelayCounter(45, 2);//最大延时45分钟，按平方计算，即4次=4*4=16分钟

    public static void resetDelayCounter() {
        delayCounter.resetZeroCount();
    }

    @Override
    public void execTask(TaskTimerSet timerSet) {
        try {
            if (timerSet.taskNameList.toLowerCase().contains("downreceiptpro")) {
                timer = timerSet;
                proConfig = ReceiptPro.getReceiptProConfig();
                downReceipt();
            }
        } catch (Exception e) {
            FGBiz.logTrace.exception(logCode, e);
        }
    }

    //下载电子回单
    private void downReceipt() {
        int beginMonthCount = timer.getParamAsInt("beginMonthCount", -1);
        int endMonthCount = timer.getParamAsInt("endMonthCount", 0);
        if (beginMonthCount > endMonthCount) {
            int chg = beginMonthCount;
            beginMonthCount = endMonthCount;
            endMonthCount = chg;
        }
        int needDownCount = 0;//需要处理的文件数
        int succDownCount = 0;//成功处理的回单数
        Date nowDay = new Date();
        for (int mthCount = beginMonthCount; mthCount <= endMonthCount; mthCount++) {
            //按日循环，取DOWNFILE表中的记录
            Date eachDay = DateHelper.addMonths(nowDay, mthCount);
            DownFileHelper dfHelper = null;
            try {
                dfHelper = new DownFileHelper(bankFront.tenant, eachDay);
                //获取该前置机该分区所有待下载的文件
                HashMap<Long, Integer> uridList = dfHelper.getAllNeedDownList(bankFront.bankCode, bankFront.code);
                if (uridList != null && uridList.size() > 0) {
                    needDownCount += uridList.size();
                    //遍历每个需要下载的文件
                    for (Map.Entry<Long, Integer> entry : uridList.entrySet()) {
                        long urid = entry.getKey();
                        //逐个执行
                        //取得要下载的文件记录
                        DownFileRecord fileRdForUpd = dfHelper.loadFromDbByUrid(urid);
                        if (fileRdForUpd != null) {
                            fileRdForUpd.downTime = new Date();
                            ExecResponse resp = downEachRdByFileRecord(fileRdForUpd);
                            if (resp.isSucceed) {
                                succDownCount++;
                                fileRdForUpd.downState = "2";
                                fileRdForUpd.downInfo = resp.getResultAsString();
                            } else {
                                fileRdForUpd.downState = "3";
                                fileRdForUpd.downInfo = resp.logMsg;
                                FGBiz.logTrace.error(logCode, "urid为" + urid + "的记录，" + resp.logMsg);
                            }
                            int rowsAff = dfHelper.updateDownState(fileRdForUpd);
                            if (rowsAff < 1) {
                                FGBiz.logTrace.info(logCode, "urid:" + urid + "的记录，更新行数：" + rowsAff);
                            }
                        } else {
                            FGBiz.logTrace.error(logCode, "urid:" + urid + "的记录，已被移除");
                        }
                    }
                } else {
                    FGBiz.logTrace.info(logCode, "取" + Format.Date6YearMonth.format(eachDay) + "线路" + bankFront.bankCode + "前置机" + bankFront.code + "的待下载文件记录为空");
                }
            } catch (Exception ex) {
                FGBiz.logTrace.exception(logCode, ex);
            } finally {
                if (dfHelper != null) {
                    dfHelper.close();
                }
            }
        }
        FGBiz.logTrace.info(logCode, "本次需下载" + needDownCount + "个ZIP文件，下载成功" + succDownCount + "个ZIP文件");
        if (succDownCount == 0) {
            delayCounter.increaseZeroCount();
            FGBiz.logTrace.info(logCode, "成功个数为0，下次执行将增加延时" + delayCounter.getDelayMinutes() + "分钟");
        } else {
            delayCounter.resetZeroCount();
            SyncReceipt.resetDelayCounter();//同步任务重新计数延时
        }
    }

    /**
     * 根据URID，进行下载及处理，返回保存成功条数
     *
     * @throws ParseException
     * @throws SQLException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws IOException
     */
    private ExecResponse downEachRdByFileRecord(DownFileRecord pFileRd) throws IllegalArgumentException {
        String localSaveSir = StringHelper.trimEndFileSp(proConfig.localSaveMainDir);//本地pdf回单保存父路径
        ExecResponse retResp = new ExecResponse();//处理结果类
        ReceiptDataHelper receiptHelper = null;//回单数据保存类，分区分表
        FtpSet ftpSet = bankFront.getFtpSet("receipt");
        ftpSet.downDir = StringHelper.trimEndFileSp(ftpSet.downDir) + "/";
        ftpSet.upDir = StringHelper.trimEndFileSp(ftpSet.upDir) + "/";
        SftpPortClient sftpPortClient = null;
        try {
            sftpPortClient = new SftpPortClient(ftpSet);
            if (!FileHelper.existFile(localSaveSir)) {
                FileHelper.mkdir(localSaveSir);
            }
            WriteBankLogLn("***********连接SFTP服务器开始***********");
            FtpReceiver receiver = sftpPortClient.downloadFile("", pFileRd.filePath, localSaveSir);

            sftpPortClient.disconnect();
            WriteBankLogLn("***********连接SFTP服务器结束***********");
            if (receiver.isCompleted) {
//            if (true) {
                WriteBankLogLn("文件下载已完成，开始解压...解压至：[" + localSaveSir + "]");
                ZipHelper.unzipFile(localSaveSir + File.separator + pFileRd.filePath, localSaveSir);
                WriteBankLogLn("文件解压已完成.开始查询回单文件数据...");
                //是否删除下载的zip临时文件
                if (proConfig.deleteAfterUploaded) {
                    WriteBankLogLn("删除" + localSaveSir + File.separator + pFileRd.filePath);
                    FileHelper.deleteFileIfExists(localSaveSir + File.separator + pFileRd.filePath);
                }

                //查询回单明细
                receiptHelper = new ReceiptDataHelper(reqHeader.tenant, pFileRd.getBusDate());
                String[] nameAndExt = StringHelper.splitFileNameAndExt(pFileRd.filePath);
                //文件名，时间_账户
                String[] info = nameAndExt[0].split("_");

                HEBBANK01Header bankHeader = new HEBBANK01Header();
                XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
                bankHeader.bsnCode = "CBE027";
                bankHeader.serialNo = getQryTransID();
                writeCommonHeader(xmlWriter, bankHeader);
                xmlWriter.writeStartElement("ReqParam");
                xmlWriter.writeElementString("saCardNo", info[1]);//卡号
                xmlWriter.writeElementString("saAcctNo", info[1]);//账号
                xmlWriter.writeElementString("saTxDt1", info[0]);//交易日期区间(开始)
                xmlWriter.writeElementString("saTxDt2", info[0]);//交易日期区间(结束)
                xmlWriter.writeEndElement();
                xmlWriter.writeEndDocument();

                String[] bankResult = sendToBank(xmlWriter.toXmlString(), bankHeader);
//                String[] bankResult = new String[]{"", "0000||#<?xml version=\"1.0\" encoding=\"GBK\" ?><SCCBEBankData><opRep><serialNo>1903424913</serialNo><opResult><pageCount>4</pageCount><qryBillInfo><row><saAcctNo>01701000000794</saAcctNo><saOpenBranch>0170</saOpenBranch><acctName>测试公司89</acctName><saTxDt>20200304</saTxDt><saTxTime>185608</saTxTime><saTxBranch>0170</saTxBranch><currCode>01</currCode><currName/><saTxLogNo>W00007000914</saTxLogNo><saTxAmt>1.00</saTxAmt><printCnts>2</printCnts><dAcctNo/><dAcctName>荣盛房地产发展股份有限公司</dAcctName><dBranchName>中国建设银行股份有限公司廊坊住房城建支行</dBranchName><remark>网上报销</remark><abstract/><abstractCode>普通汇兑</abstractCode><dcFlag>0</dcFlag><openBranchName/><acctTxSeq>670</acctTxSeq></row><row><saAcctNo>01701000000794</saAcctNo><saOpenBranch>0170</saOpenBranch><acctName>测试公司89</acctName><saTxDt>20200304</saTxDt><saTxTime>185608</saTxTime><saTxBranch>0170</saTxBranch><currCode>01</currCode><currName/><saTxLogNo>W00007000914</saTxLogNo><saTxAmt>0.50</saTxAmt><printCnts>2</printCnts><dAcctNo/><dAcctName/><dBranchName/><remark>手续费</remark><abstract/><abstractCode>收费</abstractCode><dcFlag>0</dcFlag><openBranchName/><acctTxSeq>671</acctTxSeq></row><row><saAcctNo>01701000000794</saAcctNo><saOpenBranch>0170</saOpenBranch><acctName>测试公司89</acctName><saTxDt>20200304</saTxDt><saTxTime>190935</saTxTime><saTxBranch>0170</saTxBranch><currCode>01</currCode><currName/><saTxLogNo>W00008000896</saTxLogNo><saTxAmt>1.00</saTxAmt><printCnts>2</printCnts><dAcctNo/><dAcctName>荣盛房地产发展股份有限公司</dAcctName><dBranchName>中国建设银行股份有限公司廊坊住房城建支行</dBranchName><remark>网上报销</remark><abstract/><abstractCode>普通汇兑</abstractCode><dcFlag>0</dcFlag><openBranchName/><acctTxSeq>672</acctTxSeq></row><row><saAcctNo>01701000000794</saAcctNo><saOpenBranch>0170</saOpenBranch><acctName>测试公司89</acctName><saTxDt>20200304</saTxDt><saTxTime>190935</saTxTime><saTxBranch>0170</saTxBranch><currCode>01</currCode><currName/><saTxLogNo>W00008000896</saTxLogNo><saTxAmt>0.50</saTxAmt><printCnts>2</printCnts><dAcctNo/><dAcctName/><dBranchName/><remark>手续费</remark><abstract/><abstractCode>收费</abstractCode><dcFlag>0</dcFlag><openBranchName/><acctTxSeq>673</acctTxSeq></row></qryBillInfo></opResult></opRep></SCCBEBankData>"};
                if (bankResult[0].length() == 0) {
                    String[] result = bankResult[1].split("\\|");
                    if ("0000".equals(result[0])) {
                        StringBuilder tmpSbMsg = new StringBuilder();
                        String xmlStr = bankResult[1].substring(bankResult[1].indexOf("|#") + 2);
                        XmlTextReader tmpBkReader = loadBankRespXmlReader(xmlStr, tmpSbMsg);
                        if (tmpBkReader != null) {
                            String dateCount = tmpBkReader.getFirstText("/SCCBEBankData/opRep/opResult/pageCount");
                            if (Integer.parseInt(dateCount) > 0) {
                                try {
                                    while (tmpBkReader.read("/SCCBEBankData/opRep/opResult/qryBillInfo/row")) {
                                        String pdfSavePath = localSaveSir + File.separator + nameAndExt[0] + File.separator + nameAndExt[0] + File.separator
                                                + info[1] + tmpBkReader.readedXElement.getSingleText("acctTxSeq") + ".pdf";
                                        if (FileHelper.existFile(pdfSavePath)) {
                                            //返回报文与我们需要数据之间的对应
                                            ReceiptData eachData = new ReceiptData();
                                            /**回单唯一标识（在银行端的唯一标识（该账号的唯一），如招行的打印实例号）*/
                                            eachData.istNbr = tmpBkReader.readedXElement.getSingleText("saTxLogNo");
                                            /**回单关联号（回单编号）*/
                                            eachData.receiptNo = eachData.istNbr;
                                            /**业务参考号*/
                                            eachData.busRef = eachData.istNbr;
                                            /**银行流水号*/
                                            eachData.bnkSeqNo = eachData.istNbr;
                                            /**本方账号*/
                                            eachData.ownAct = pFileRd.ownAct;
                                            /**银行代码，如工行102*/
                                            eachData.bank = banks;
                                            /**线路代码（来源渠道），如工行直联ICBC02*/
                                            eachData.srcSys = this.bankFront.bankCode;
                                            /**日期*/
                                            eachData.busDate = pFileRd.busDate;
                                            /**对方账号*/
                                            eachData.oppActNum = tmpBkReader.readedXElement.getSingleText("dCardNo");
                                            /**对方户名*/
                                            eachData.oppActName = tmpBkReader.readedXElement.getSingleText("dAcctName");
                                            /**交易方向*/
                                            String cdFlag = tmpBkReader.readedXElement.getSingleText("dcFlag");//借贷标志
                                            if ("0".equals(cdFlag)) {
                                                eachData.moneyWay = "1";
                                            } else if ("1".equals(cdFlag)) {
                                                eachData.moneyWay = "2";
                                            }
                                            /**币种*/
                                            eachData.cur = convertCurToATS(tmpBkReader.readedXElement.getSingleText("currCode"));
                                            eachData.amount = new BigDecimal(tmpBkReader.readedXElement.getSingleText("saTxAmt"));

                                            /**回单文件--本地文件相对路径*/
                                            eachData.localFile = StringHelper.getRelativePath(pdfSavePath, localSaveSir);
                                            /**源文件路径*/
                                            eachData.srcFile = pdfSavePath;
                                            /**回单文件类型*/
                                            eachData.fileType = "1";
                                            /**下载状态：指从银行下载该回单文件的状态，1未下载；2已下载；3下载失败；4下载中*/
                                            eachData.downState = "2";
                                            /**下载时间*/
                                            eachData.downTime = new Date();
                                            /**下载信息，如果失败则为失败原因*/
                                            eachData.downInfo = "下载成功";
                                            /**上传状态：指文件从银行端下载完成后，上传至ftp或ats或oss或客制化文件服务的状态，1未上传；2已上传；3上传失败；4上传中*/
                                            eachData.upState = "1";
                                            /**推送状态：指文件上传完成后，回单数据推送至ats或客制化平台的状态，1未推送；2已推送；3推送失败；4推送中*/
                                            eachData.pushState = "1";
                                            /**创建时间*/
                                            eachData.createdOn = new Date();
                                            /**最后修改时间*/
                                            eachData.lastModifiedOn = new Date();
                                            /**版本号*/
                                            eachData.rowVersion = 1;
                                            receiptHelper = new ReceiptDataHelper(reqHeader.tenant, eachData.getBusDate());
                                            //回单数据记录入库
                                            int inRe = receiptHelper.insertIfNotExist(eachData);
                                            if (inRe > 0) {
                                                retResp.isSucceed = true;
                                                retResp.rdCount++;
                                            } else {
                                                FGBiz.logTrace.info(logCode, eachData.receiptNo + "写入数据库，影响行数：" + inRe);
                                            }
                                        } else {
                                            WriteBankLogLn("流水号为：" + tmpBkReader.readedXElement.getSingleText("saTxLogNo") + "的回单数据文件不存在，如有必要，请联系银行处理");
                                        }
                                    }
                                } catch (Exception ex) {
                                    this.WriteBankLogLn(ex);
                                } finally {
                                    if (receiptHelper != null) {
                                        receiptHelper.close();
                                    }
                                }
                            } else {
                                WriteBankLogLn("查询" + info[0] + "日回单数据失败,原因:返回回单数据为空");
                                retResp.logMsg = "查询" + info[0] + "日回单数据失败,原因:返回回单数据为空";
                            }
                        } else {
                            WriteBankLogLn("查询" + info[0] + "日回单文件失败,原因:" + tmpSbMsg.toString());
                            retResp.logMsg = "查询" + info[0] + "日回单文件失败,原因:" + tmpSbMsg.toString();
                        }
                    } else {
                        WriteBankLogLn("查询" + info[0] + "日回单文件失败,原因:" + result[1]);
                        retResp.logMsg = "查询" + info[0] + "日回单文件失败,原因:" + result[1];
                    }
                } else {
                    WriteBankLogLn("查询" + info[0] + "日回单文件失败,原因:" + bankResult[1]);
                    retResp.logMsg = "查询" + info[0] + "日回单文件失败,原因:" + bankResult[1];
                }
            } else {
                WriteBankLogLn("连接SFTP失败，请检查配置、通道是否正常,文件是否存在。失败原因：\r\n" + receiver.connMsg);
            }
        } catch (Exception ex) {
            retResp.logMsg = LogHelper.getStackTrace(ex);
            FGBiz.logTrace.exception(logCode, ex, "异常的文件路径：" + pFileRd.filePath);
        } finally {
            if (receiptHelper != null) {
                receiptHelper.close();
            }
        }
        WriteBankLogLn("本次共下载：" + retResp.rdCount + "个PDF文件。");

        return retResp;
    }
}
